package proxy

import (
	"context"
	"errors"
	"fmt"
	"go-proxy/common"
	"go-proxy/config"
	"net/http"
	"time"
)

var (
	RestartChan = make(chan RestartData)
)

// InitProxy 代理服务初始化
func InitProxy() {
	proxyData := config.ProxyConfigData
	proxy := proxyData.Proxy
	if len(proxy.Servers) <= 0 {
		common.LogError("proxy server is empty")
		return
	}

	for _, server := range proxy.Servers {
		ServerStart(&server)
	}

	go serverCheckStatus()
}

// ServerStart 代理服务启动
func ServerStart(server *config.ProxyServer) error {
	// 为每个服务器创建一个新的ServeMux
	mux := http.NewServeMux()
	if server.Type == common.HttpProxy {
		mux.Handle("/", &TransProxy{
			server: server,
		})
	}

	if server.Type == common.WebProxy {
		if len(server.FileRoot) <= 0 {
			server.FileRoot = common.DefaultFileRoot
		}
		mux.Handle("/", &WebProxy{
			fileServer: http.FileServer(http.Dir(server.FileRoot)),
			server:     server,
		})
	}

	httpServer := &http.Server{
		Addr:    fmt.Sprintf(":%d", server.Port),
		Handler: mux,
	}
	setServer(server.Name, httpServer)

	// 启动服务器
	common.LogInfo(server.Name, " 反向代理服务器启动: port=", server.Port)
	setServerStatus(server.Name, true)
	go func() {
		if err := httpServer.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
			common.LogError(server.Name, " 服务器启动失败:", err)
			setServerStatus(server.Name, false)
		}
	}()
	return nil
}

// restartListener 监听代理服务重启信号
func restartListener() {
	for {
		restartData := <-RestartChan
		common.LogInfo("重启服务: serverName=", restartData.ServerName)
		ShutdownServer(restartData.ServerName)
		server := getProxyServerConfig(restartData.ServerName)
		if server != nil {
			ServerStart(server)
		}
	}
}

func HandleRestartServer(name string) error {
	serverConfig := getProxyServerConfig(name)
	if serverConfig == nil {
		return fmt.Errorf("server config not found")
	}

	status := GetServerStatus(name)
	if status {
		ShutdownServer(name)
	}

	return ServerStart(serverConfig)
}

func getProxyServerConfig(name string) *config.ProxyServer {
	proxyConfig := config.ProxyConfigData.Proxy
	for _, server := range proxyConfig.Servers {
		if server.Name == name {
			return &server
		}
	}
	return nil
}

// ShutdownServer 关闭代理服务器
func ShutdownServer(name string) {
	server := getServer(name)
	if server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
		defer cancel()
		if err := server.Shutdown(ctx); err != nil {
			msg := fmt.Sprintf("%s 服务器关闭失败:", name)
			common.LogError(msg, err)
		} else {
			msg := fmt.Sprintf("%s 反向代理服务成功关闭", name)
			common.LogInfo(msg)
			setServerStatus(name, false)
		}
	}
}
